package cn.le.lambda.example1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 *
 * Predicate<T> : 断言,就是对一个对象或者基本数据作出判断,为false或true
 * Consumer<T> : 代表一个执行操作.它的抽象方法接受单个参数且没有结果(返回值void),抽象方法对象指定的参数t执行一个操作
 * Funciont<R,R> : 接受一个参数,产生一个结果(一个返回值),T表示抽象方法的参数类型,R表示抽象方法的返回值类型
 *   R apply(T t):该抽象方法代表着对参数T t执行一个功能(function),比如执行一个提取或者转化功能,得到
 *   类型为R的结果,T t是执行功能的原材料,R是执行功能的目标结果的类型
 * BiFunction<T,U,R>的功能可以接受两个参数,并产出一个结果,第一 二个是参数,第三个是返回值
 */
public class Test {

    //业务要求 , 查找满足条件的会员
    public static void main(String[] args) {

        //保存所有会员的信息
        List<Person> roster = new ArrayList<>();


        //1.利用实现类来做
        printPersons(roster,new CherkImpl());
        //2.利用匿名类不类来实现,这里就需要写实现类了
        printPersons(roster, new CherkPerson(){
            public boolean test(Person p)
            {
                return p.getGender() == Person.Sex.MALE
                        && p.getAge() >= 18 && p.getAge() <= 25;
            }
        });
        //3.利用Lambda来做,Lambda表达式实际上是函数式接口的唯一抽象方法的实现,所以传过去一个lambda表达式就相当于传过去了一个函数接口的实现
        printPersons(roster,
                p -> p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18 && p.getAge() <= 25);

        //4.利用jdk自带的标准函数式接口,这样就不需要自己创建接口了
        printPersonsWithpredicate(roster,person -> person.getGender() == Person.Sex.MALE
                && person.getAge() >= 18 && person.getAge() <= 25);

        //5.全部都是使用lambda表示达
        processPersons(roster,p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18
            && p.getAge() <= 25, p -> p.printPerson());

        //6 使用lambda打印对象的属性值
        processPersonsWithFunction(roster,person -> person.getGender() == Person.Sex.MALE
                && person.getAge() >= 18 && person.getAge() <= 25,
                p -> p.getEmailAddress(),
                email -> System.out.println(email));

        //7 lambda与泛型结合
        processElements(roster,person -> person.getGender() == Person.Sex.MALE
                        && person.getAge() >= 18 && person.getAge() <= 25,
                p -> p.getEmailAddress(),
                email -> System.out.println(email));

        // 8 使用聚合函数
        processWithAggregate(roster,person -> person.getGender() == Person.Sex.MALE
                        && person.getAge() >= 18 && person.getAge() <= 25,
                p -> p.getEmailAddress(),
                email -> System.out.println(email));
        //----------------------------------------------------

        //lambda

    }

    /**
     * 使用聚合操作,并用lambda表达式作为聚合操作的参数
     * @param source
     * @param tester
     * @param mapper
     * @param block
     * @param <X>
     * @param <Y>
     */
   public static <X,Y> void  processWithAggregate(
           Collection<X> source,Predicate<X> tester,
           Function<X,Y> mapper,Consumer<Y> block)
   {
        //source.stream().filter(tester).map(mapper).forEach(block);
   }

    //利用泛型提高方法的舒适性
    public static <X,Y> void processElements(Iterable<X> source,
                                                  Predicate<X> tester, Function<X,Y> mapper,
                                                  java.util.function.Consumer<Y> block)
    {
        for(X p : source)
        {
            if (tester.test(p))
            {
                Y data = mapper.apply(p);
                block.accept(data);
            }
        }
    }
    //利用lambda表达式,打印出对象的某一个属性值
    public static void processPersonsWithFunction(List<Person> roster,
                                                  Predicate<Person> tester, Function<Person,String> mapper,
                                                  java.util.function.Consumer<String> block)
    {
        for(Person p : roster)
        {
            if (tester.test(p))
            {
                String data = mapper.apply(p);
                block.accept(data);
            }
        }
    }
    //筛选会员,利用自定义函数式接口,并打印会员信息
    public static void printPersons(List<Person> roster,CherkPerson tester)
    {
        for (Person p : roster) {
            if(tester.test(p))
            {
                //打印会员信息
                p.printPerson();
            }
        }
    }
    //筛选会员,利用jdk标准的函数式接口,并打印会员信息
    public static void printPersonsWithpredicate(List<Person> roster, Predicate<Person> tester)
    {
        for (Person p : roster) {
            if(tester.test(p))
            {
                //打印会员信息
                p.printPerson();
            }
        }
    }
    //筛选会员,全部用函数式编程
    public static void processPersons(List<Person> roster,
                                      Predicate<Person> tester,Consumer<Person> block)
    {
        for (Person p : roster) {
            if(tester.test(p))
            {
                block.accept(p);
            }
        }


    }


}
class CherkImpl implements CherkPerson
{
    //筛选会员的条件
    public boolean test(Person p)
    {
        return p.getGender() == Person.Sex.MALE
                && p.getAge() >= 18 && p.getAge() <= 25;
    }

}
